#!/user/bin/env python
# -*-coding:utf-8-*-
'''
@author: Patty
@project: automation_framework
@file: extractdata.py
@time: 2020/5/11  15:53
@IDE: PyCharm 
'''

import logging,requests
from jsonpath import jsonpath
import base.globalvars as glo
from proj_spec.DAS.misc import notify
from util.db_util import execute_query
from proj_spec.DAS.model import get_model_id
from proj_spec.DAS.element import get_element_id

def __init():
    """"""
    from base.get_config import get_header_file
    from base.getdata import get_header
    global url1, url2, header1, header2
    url1 = glo.get_value('url1')
    url2 = glo.get_value('url2')
    header1 = get_header(get_header_file(), "header1")
    header2 = get_header(get_header_file(), "header2")

def get_extract_data_ids(**kwargs):
    """根据参数获取extract_data_id

    :return:
    """
    assert set(kwargs.keys()) < {'model_id','element_id','file_id','status'},"指定参数应为'model_id','element_id','file_id','status'之一"
    condition = ""
    for key in kwargs.keys():
        if type(kwargs[key]) is str:
            condition += " and %s='%s'"%(key,kwargs[key])
        else:
            condition += " and %s=%s" % (key, kwargs[key])

    condition = condition.lstrip(" and")
    sql = """SELECT id FROM t_das_extract_data WHERE %s"""%condition

    result = execute_query(sql,result_type='dict')
    return [row['id'] for row in result]

def get_extract_data_id(model_name, element_name, file_id):
    """获取指定模型、元素、文件的提取数据id

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id

    :return: 提取数据id
    """

    try:
        model_id = get_model_id(model_name=model_name)
        element_id = get_element_id(model_name=model_name, element_name=element_name)
        ids = get_extract_data_ids(model_id=model_id, element_id=element_id, file_id=file_id)
        assert len(ids) > 0
        return ids[0]
    except Exception as e:
        logging.error("no result retrieved")
        return None


def get_extract_data_table_data(model_name, element_name, file_id, row_index, col_index):
    """获取指定模型、元素、文件提取表格指定行、列的数据

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id
    :param row_index: 行坐标
    :param col_index: 列坐标

    :return: 符合参数条件的extract_data_table记录
    """

    sql = "SELECT * FROM t_das_extract_table WHERE data_id=(SELECT id FROM t_das_extract_data WHERE model_id=" \
          "(SELECT id FROM t_das_model WHERE model_name='%s') AND element_id=" \
          "(SELECT id FROM t_das_model_element WHERE model_id= (SELECT id FROM t_das_model WHERE model_name='%s') " \
          "AND element_name='%s') AND file_id=%d) AND row_index=%d AND col_index=%d"\
          %(model_name, model_name, element_name, file_id, row_index, col_index)
    results = execute_query(sql,result_type="dict")

    try:
        result = results[0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return None


def get_extract_data_text_id(model_name, element_name, file_id, seq):
    """获取指定模型、元素、文件、序列的id

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id
    :param seq: 序列号

    :return: 提取数据文本id
    """
    results = execute_query(
        "SELECT id FROM t_das_extract_text WHERE data_id=(SELECT id FROM t_das_extract_data WHERE model_id="
        "(SELECT id FROM t_das_model WHERE model_name='%s') AND element_id=(SELECT id FROM t_das_model_element WHERE model_id="
        "(SELECT id FROM t_das_model WHERE model_name='%s') AND element_name='%s') AND file_id=%d) AND seq=%d" % (
            model_name, model_name, element_name, file_id, seq))
    try:
        result = results[0][0]
        return result
    except Exception as e:
        logging.error("no result retrieved")
        return None

def get_extract_data_info(**kwargs):
    """获取指定的提取数据

    :param extract_data_id:

    :return: 指定id对应的提取数据
    """
    try:
        if 'extract_data_id' in kwargs:
            sql = "SELECT * FROM t_das_extract_data WHERE id=%s"%kwargs['extract_data_id']
        else:
            sql = "SELECT * FROM t_das_extract_data WHERE model_id=%s and element_id=%s and file_id=%s" % (kwargs['model_id'],kwargs['element_id'],kwargs['file_id'])
        res = execute_query(sql,result_type="dict")
        return res[0]
    except Exception as e:
        logging.error(e)
        return None

# def extract_data(file_id, model_id, element_id):
#     """提取指定文件元素
#
#     :param file_id: 文件id
#     :param model_id: 模型id
#     :param element_id: 元素id
#
#     :return:
#     """
#
#     __init()
#     url = url1 + "/api/v1/ExtractData/extract"
#     payload = {"FileId":file_id,"ModelId":model_id,"ElementId":element_id}
#     res = requests.post(url, headers = header2, json = payload)
#     assert res.status_code==200, "提取元素失败： 文件id %s 元素 %s"%(file_id, element_id)

def reset_data(file_id, model_id, element_id, manually_maintained=True, need_notify=False):
    """对指定文件元素进行数据重置
    Todo: 默认仅对状态为人工维护的数据进行重置，并添加是否通知参数

    :param file_id: 文件id
    :param model_id: 模型id
    :param element_id: 元素id
    :param manually_maintained: 是否仅针对手工维护状态的数据做重置，默认为True
    :param need_notify: 是否需要通知（由于自动化测试和手工测试在同一环境，自动化用例重置数据时可能会对当前正进行的手工测试造成影响，因此发送通知邮件）

    :return: True-成功， False: 失败
    """
    __init()
    data_reset_url = url1 + '/api/v1/ExtractData/reset'
    payload = {"FileId": file_id, "ModelId": model_id, "ElementId": element_id}

    if manually_maintained:
        status = get_extract_data_info(file_id=file_id,model_id=model_id,element_id=element_id)['status']
        if status==1:
            res = requests.post(data_reset_url, headers=header2, json=payload)
        else:
            return True
    else:
        res = requests.post(data_reset_url, headers=header2, json=payload)

    if res.status_code==200:
        if need_notify:
            notify("重置人工维护的数据：file %s model %s element %s has been reset" % (file_id, model_id, element_id))
        return True
    else:
        logging.error("数据重置失败：%s 文件 %s 元素 %s"%(res.text, file_id, element_id))
        return False

def modify_extract_table_data(model_name,element_name,file_id,row_index,col_index, override_value = None):
    """修改提取数据

    :param model_name: 模型名称
    :param element_name: 元素名称
    :param file_id: 文件id
    :param row_index: 行号
    :param col_index: 列号
    :param override_value: overridden_value的设置值, 若为空，则使用原始值覆盖

    :return: True: 修改成功 False: 修改失败
    """

    __init()
    # model_id = get_model_id(model_name)
    # element_id = get_element_id(model_name, element_name)
    extract_table_data = get_extract_data_table_data(model_name, element_name, file_id, row_index, col_index)
    assert extract_table_data is not None,"获取extract_table_data失败：model_name %s,element_name %s,file_id %s,row_index %s,col_index %s"\
                                          %(model_name,element_name,file_id,row_index,col_index)

    if override_value is None:
        override_value = extract_table_data['original_value']

    payload = {"MergeGroup": extract_table_data['merge_group'],
               "RowIndex": row_index,
               "ColIndex": col_index,
               "OriginalValue": extract_table_data['original_value'],
               "OverrideValue": override_value,
               "OverrideBy": "Automation",
               "OverrideTime": None,
               "OverrideNote": None,
               "RowKey": extract_table_data['row_key'],
               "Id": extract_table_data['id'],
               "DataId": extract_table_data['data_id'],
               "Seq": extract_table_data['seq'],
               "Page": extract_table_data['page'],
               "X": extract_table_data['x'],
               "Y": extract_table_data['y'],
               "Dx": extract_table_data['dx'],
               "Dy": extract_table_data['dy'],
               "DataType": 1}

    url = url1 + "/api/v1/ExtractTable/%s" % extract_table_data['id']
    res = requests.put(url, headers=header2, json=payload)
    if res.status_code == 200:
        return True
    else:
        logging.error("修改提取数据失败：%s" % res.text)
        return False


def get_extract_data(file_id, model_id, element_id):
    __init()

    #extract_res = requests.get(url2+"/api/v1/ex/ExtractDataEx/get-dynamic-table?FileId=%s&ModelId=%s&ElementId=%s&_v=1637129088523"%(file_id, model_id, element_id), headers = header1)
    extract_res = requests.get(
        url2 + "/api/v1/ex/ExtractDataEx/filter/join?ModelId=%s&ElementId=%s&FileId=%s" % (
        model_id, element_id, file_id), headers=header1)
    assert extract_res.status_code==200,"获取提取数据失败"
    return extract_res.json()


def execute_extract(file_id, model_id, element_id, version = 2, return_all = False):
    """客户端手动提取元素

    :param file_id: 文件id
    :param model_id: 模型id
    :param element_id: 元素id
    :param version: 提取接口的版本号, 1或2（2为新版本提取）
    :param return_all: 获取所有推荐结果，默认仅返回推荐级别最高的第一个结果

    :return: 提取接口返回数据
    """

    __init()
    if version==1:
        extract_url = url1 + '/api/v1/ExtractData/extract'
    else:
        extract_url = url1 + '/api/v1/ExtractData/extract?useClusterFeatureExtract=true'
    requests_body = {"FileId": file_id, "ModelId": model_id, "ElementId": element_id}

    extract_res = requests.post(url=extract_url, headers=header2, json=requests_body)
    assert extract_res.status_code == 200, '提取接口失败'
    result = extract_res.json()
    if return_all:
        return result
    else:
        return jsonpath(result, "$[?(@.recommendLevel==1)]")[0]


def save_extract_data(extract_data):
    __init()
    url = url1 +  "/api/v1/ExtractData/extract/save"
    post_data = extract_data
    res = requests.post(url, headers = header2, json = post_data)
    assert res.status_code==200, "保存提取数据失败： file id %s, model id %s, element id %s"%(extract_data['FileId'], extract_data['ModelId'], extract_data['ElementId'])

def reset_extract_data(file_id, model_id, element_id):
    """

    :param file_id:
    :param model_id:
    :param element_id:
    :return:
    """
    __init()
    url = url1 + "/api/v1/ExtractData/reset"
    payload = {"FileId":file_id,"ModelId":model_id,"ElementId":element_id}
    res = requests.post(url, headers = header2, json=payload)
    assert res.status_code==200,"数据重置失败： fild id %s, model id %s, element id %s"%(file_id, model_id, element_id)

def set_extract_data_to_manually_maintained(file_id, model_id, element_id):
    extract_data = execute_extract(file_id, model_id, element_id, version = 2, return_all = False)
    save_extract_data(extract_data)

